package com.woniuxy.cloud.userassembly.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.woniuxy.cloud.api.dto.LoginDto;

import com.woniuxy.cloud.api.dto.RoleDto;
import com.woniuxy.cloud.api.dto.UserDto;
import com.woniuxy.cloud.api.param.DepositLevelParam;
import com.woniuxy.cloud.api.param.RoleIdAndAreaParam;
import com.woniuxy.cloud.areaApi.AreaQueryAPI;

import com.woniuxy.cloud.areaApi.dto.AreaDto;
import com.woniuxy.cloud.demo.Result;
import com.woniuxy.cloud.dto.BaseDto;
import com.woniuxy.cloud.userassembly.annotation.Validate;
import com.woniuxy.cloud.userassembly.components.JWTHelper;
import com.woniuxy.cloud.userassembly.entity.Role;
import com.woniuxy.cloud.userassembly.entity.User;
import com.woniuxy.cloud.userassembly.entity.UserRole;
import com.woniuxy.cloud.userassembly.exception.UserException;
import com.woniuxy.cloud.userassembly.mapper.UserMapper;
import com.woniuxy.cloud.userassembly.param.*;
import com.woniuxy.cloud.userassembly.service.RoleService;
import com.woniuxy.cloud.userassembly.service.UserRoleService;
import com.woniuxy.cloud.userassembly.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.cloud.userassembly.util.PageMysqlUtil;
import com.woniuxy.cloud.userassembly.util.WoniuBeanUtils;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 周川雄
 * @since 2022-01-26
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private JWTHelper jwtHelper;

    @Resource
    private UserRoleService urs;

    @Resource
    private RoleService rs;

    @Resource
    private AreaQueryAPI areaQueryAPI;


    @Override
    public LoginDto login(String username) {
        User user = getOne(new QueryWrapper<User>().eq("user_account", username)
                .eq("user_del", 0));
        if (user == null) {
            throw new RuntimeException("没有此账号");
        }
        LoginDto userDto = WoniuBeanUtils.copyObject(user, LoginDto.class);
        //登录成功后，生成token
        Map<String, Object> map = new HashMap<>();
        map.put("user", userDto);
        Date date = DateUtils.addDays(new Date(), 1);
        String jwt = jwtHelper.createJWT(date, map);
        userDto.setToken(jwt);
        return userDto;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserDto SaveUser(SaveUserParam sup) {
        QueryWrapper<User> query = new QueryWrapper<>();
        //用户名和电话不能重乎
        query.and(wrapper -> wrapper
                .eq("user_account", sup.getUserAccount())
                .or()
                .eq("user_phone", sup.getUserPhone())
        );
        List<User> list = list(query);

        if (null == list || list.size() <= 0) {
            User userTable = WoniuBeanUtils.copyObject(sup, User.class);
            userTable.setUserDel(0);
            //密码加密
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            userTable.setUserPassword(passwordEncoder.encode(userTable.getUserPassword()));
            if (save(userTable)) {
                //添加用户成功,如果是是普通用户
                if (sup.getIsUser() == 0) {
                    //清空角色账号的关联角色
                    //urs.remove(new QueryWrapper<UserRole>().eq("user_id", userTable.getUserId()));
                    UserRole userRole = new UserRole();
                    userRole.setUserId(userTable.getUserId());
                    userRole.setRoleId(0);
                    urs.save(userRole);
                }
                return WoniuBeanUtils.copyObject(userTable, UserDto.class);
            }

            throw new UserException("新用户添加失败", 10305);

        } else {
            for (User userTable : list) {

                if (sup.getUserAccount().trim().equals(userTable.getUserAccount().trim())) {
                    throw new UserException("新用户添加失败，用户名重复", 10306);
                }
                if (sup.getUserPhone().trim().equals(userTable.getUserPhone().trim())) {
                    throw new UserException("新用户添加失败，电话重复", 10307);
                }
            }
        }
        return null;
    }

    @Override
    public BaseDto<UserDto> listUsers(UserPageAndByKeyParam upp) {
        QueryWrapper<User> query = new QueryWrapper<>();

        //模糊查询3个字段
        if (!StringUtils.isEmpty(upp.getKey())) {
            query.and(wrapper -> wrapper
                    .like("user_account", upp.getKey())
                    .or()
                    .like("user_phone", upp.getKey())
                    .or()
                    .like("user_name", upp.getKey())
            );
        }
        query.eq("user_del", 0);
        query.orderByDesc("user_id");

        return PageMysqlUtil.pageQuery(UserDto.class, this, query, new BaseParam(upp.getIndexPage(), upp.getPageSize()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveUserRole(SaveUserRoleParam arp) {
        //先判断用户是否存在
        User user = getOne(new QueryWrapper<User>()
                .eq("user_id", arp.getUserId())
                .eq("user_del", 0));

        if (StringUtils.isEmpty(user)) throw new UserException("该用户不存在,不能选择角色", 10405);
        //清空角色账号的关联角色
        urs.remove(new QueryWrapper<UserRole>().eq("user_id", arp.getUserId()));
        //当不勾选任何角色，只勾选账户
        if (arp.getRoleIds() == null || arp.getRoleIds().size() == 0) return true;
        //获取所有可以勾选的角色
        List<Role> roles = rs.list(new QueryWrapper<Role>().in("role_id", arp.getRoleIds()).eq("role_status", 0));

        if (roles.size() != arp.getRoleIds().size()) throw new UserException("授权失败，当前勾选角色不存在或者已经被删除", 10406);

        List<UserRole> list = arp.getRoleIds().stream().map(
                id -> {
                    UserRole war = new UserRole();
                    war.setRoleId(id);
                    war.setUserId(arp.getUserId());
                    return war;
                }).collect(Collectors.toList());
        return urs.saveBatch(list);
    }

    @ExceptionHandler(Exception.class)
    @Override
    public boolean removeUserByIds(List<Integer> ids) {
        List<User> users = list(new QueryWrapper<User>().in("user_id", ids).eq("user_del", 0));
        if (ids.size() != users.size()) throw new UserException("用户删除失败，请检查用户是否存在或者已经删除", 10407);
        for (User user : users) {
            user.setUserDel(1);
        }
        return updateBatchById(users);
    }

    @GlobalTransactional
    @Validate
    @ExceptionHandler(Exception.class)
    @Override
    public boolean UpdateMyselfParam(UpdateMyselfParam ump) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String userId = request.getHeader("userId");
        User user = getOne(new QueryWrapper<User>().eq("user_id", userId).eq("user_del", 0));
        if (StringUtils.isEmpty(user)) throw new UserException("用户修改失败，请检查用户是否存在或者已经删除", 10408);
        if (!user.getUserPhone().equals(ump.getPhone())) throw new UserException("电话号码和数据库对应不上", 10409);

        User userTable = WoniuBeanUtils.copyObject(ump, User.class);

        //如果老电话和新电话不相同
        if (!ump.getPhone().equals(ump.getPhone())) {
            User one = getOne(new QueryWrapper<User>().eq("user_phone", ump.getUserPhone()).eq("user_del", 0));
            if (null != user) throw new UserException("电话号码已经存在，修改失败", 10410);
            userTable.setUserPhone(ump.getPhone());
        }

        //判断密码是否修改，修改以后加密
        if (!StringUtils.isEmpty(ump.getUserPassword())) {
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            userTable.setUserPassword(passwordEncoder.encode(ump.getUserPassword()));
        }
        return updateById(userTable);
    }

    @Override
    public UserDto findUserById(Integer userId) {
        User user = getOne(new QueryWrapper<User>().eq("user_id", userId).eq("user_del", 0));
        if (StringUtils.isEmpty(user)) {
            return null;
        } else {
            return WoniuBeanUtils.copyObject(user, UserDto.class);
        }

    }

    @GlobalTransactional
    @Override
    public UserDto updateUserDepositLevel(DepositLevelParam param) {
        User user = getOne(new QueryWrapper<User>().eq("user_id", param.getUserId()).eq("user_del", 0));
        if (StringUtils.isEmpty(user)) throw new UserException("该用户不存在,不能选择角色", 10412);
        user.setDepositLevel(param.getDepositLevel());
        user.setDepositId(param.getDepositId());
        if (!updateById(user)) throw new UserException("用户押金等级修改失败", 10413);
        return WoniuBeanUtils.copyObject(user, UserDto.class);
    }

    @Override
    public List<UserDto> listUserByRoleIdAndArea(RoleIdAndAreaParam param) {
        QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("t3.role_id", param.getRoleId());

        if (!StringUtils.isEmpty(param.getAreaId())) {
            Result<List<AreaDto>> listResult = areaQueryAPI.listInitiationArea(param.getAreaId());
            List<AreaDto> data = listResult.getData();
            if (data.size() == 0 || null == data) throw new UserException("此区域暂未开通", 10414);

            List<Integer> ids = data.stream().map(
                    id -> id.getId()
            ).collect(Collectors.toList());


            wrapper.in("t1.area_id", ids);
        }


        List<User> users = baseMapper.listUser(wrapper);
        return WoniuBeanUtils.copyList(users, UserDto.class);
    }

    @Override
    public List<RoleDto> findRoleByUserId(Integer userId) {
        User one = getOne(new QueryWrapper<User>().eq("user_id", userId).eq("user_del", 0));
        if (StringUtils.isEmpty(one)) throw new UserException("暂无此用户", 10415);
        List<UserRole> list = urs.list(new QueryWrapper<UserRole>().eq("user_id", userId));
        if (StringUtils.isEmpty(list) || list.size() == 0) throw new UserException("该用户暂无绑定角色", 10416);
        List<Integer> collect = list.stream().map(
                id -> id.getRoleId()
        ).collect(Collectors.toList());
        return WoniuBeanUtils.copyList(rs.list(new QueryWrapper<Role>().in("role_id",collect).eq("role_status",0)),RoleDto.class);
    }
}
